home *** CD-ROM | disk | FTP | other *** search
- #include "debug.h"
- #include <Icons.h>
- #include "ControlStrip.h"
- #include <Gestalt.h>
-
- /**************
- Debugger Strip GH, a simple demonstration of how to write a
- control strip module. 11/27/94, version 1.2.1
- **
- changes:
- • added balloon help
- • now use a slightly different method to determine if a debugger
- is installed.
- • Now use the SetupA4 routines, not because I need them here, but
- you will need them if you want to use string constants while using
- CodeWarrior; without A4 setup, the compiler won't be able to find
- the data for declarations like:
- Str255 driverName = "\p.AppleCD";
-
- **
- In case you can't use the enclosed CodeWarrior project, you should
- use this code to compile a code resource of type 'sdev' and resID 0,
- and merge it into the enclosed control strip module.
-
- **
-
- This module simply drops into MacsBug when clicked.
- Command clicking brings up a menu of ways to drop into Macsbug. You
- can add different ways by adding items to the appropriate STR# resources
- (id 998 = menu itms and id 999 = debugger strings).
-
- Read the OS 6 Tech note.
-
- On the Develop Bookmark 19 CD there is another example control strip module
- called "MacCalender".
-
- ControlStrip.h is now with the Universal headers.
-
- Remember to change the creator for your own modules.
-
- Problems I've noticed:
- * SBTrackSlider appears to be broken; it doesn't return the correct value
- * SBGetDetachedIndString doesn't necessarily return a null string if the
- index is invalid
- * Think Reference has incorrect declarations for the icon suite routines
- Use the official Apple Icons.h file.
- * This module doesn't dehilite if the user drags outside its rect like
- it ought to. This is because I need to handle the mouse click manually if I
- want to be able to show a menu. .
-
- --glenn howes
- grhowes@kagi.com
- *****************/
- #ifdef __MWERKS__
- #include <A4Stuff.h>
- #endif
-
-
- pascal long main (long message, long params, Rect *statusRect, GrafPtr statusPort)
- {
- long result = 0L;
-
- #ifdef __MWERKS__
- long oldA4 = SetCurrentA4(); // needed only if you want to have inline strings
- #endif
- switch (message)
- {
- case sdevPeriodicTickle: // idle routine
- // result = DoCSPeriodic((MyGlobalHandle) params, statusRect, statusPort);
- break;
- case sdevInitModule: // check environs, allocate globals
- result = DoCSInit(); // return allocated globals handle or -1 for failure
- break;
- case sdevCloseModule: // release my memory
- DoCSClose((MyGlobalHandle) params);
- break;
- case sdevFeatures: // I want to handle mouseclicks myself, and I support balloon help
- result = (1L << sdevWantMouseClicks) | (1L << sdevDontAutoTrack)
- | (1L << sdevHasCustomHelp);
- break;
- case sdevGetDisplayWidth:
- result = 16L; // size of a small icon width
- break;
- case sdevDrawStatus: // draw my icon
- DoCSDraw((MyGlobalHandle) params, statusRect, statusPort);
- break;
- case sdevMouseClick: // the mouse was clicked in my button
- result = DoCSClick((MyGlobalHandle) params, statusRect, statusPort);
- break;
- case sdevSaveSettings: // DoCSClick must have returned a 2 sometime
- DoCSSavePrefs((MyGlobalHandle) params);
- break;
- case sdevShowBalloonHelp:
- result = DoCSBalloonHelp((MyGlobalHandle) params, statusRect);
- break;
-
- }
- #ifdef __MWERKS__
- SetA4( oldA4 );
- #endif
- return (result);
- }
- long DoCSBalloonHelp(MyGlobalHandle myGlobals, Rect *statusRect)
- {
- Str255 aString;
-
- SBGetDetachedIndString(aString, (*myGlobals)->utilityStrings, kHelpString);
-
- return (SBShowHelpString(statusRect, aString));
- }
- /***********
- DoCSPeriodic, remember to uncomment the call to this routine in the main routine.
-
- The Control Strip will constantly be calling your module, so be a good
- strip citizen. Don't use a periodic routine if you don't need to, and
- use a large kTickleLength if your periodic code routine is time consuming
- I use 120 (2 seconds)
-
- ***********/
- long DoCSPeriodic(MyGlobalHandle myGlobals, Rect *statusRect, GrafPtr statusPort)
- {
- unsigned long ticks, lastTicks;
- unsigned long mask = 1L<<31;
-
- ticks = TickCount();
- lastTicks = (*myGlobals)->lastTicks;
- if (ticks >= lastTicks // either we've waited at least kTickleLength
- || ((lastTicks & mask) && !(ticks & mask)))// or mac was on for 2 years and ticks wrapped (it could happen)
- {
- (*myGlobals)->lastTicks = ticks + kTickleLength;
- // insert your periodic code here
-
- }
- return (0L);
- }
- /******
- If I returned a value with the #1 bit set (a 2 for instance) in response to
- a sdevPeriodicTickle or sdevMouseClick, I will receive this message
-
- *********/
- void DoCSSavePrefs(MyGlobalHandle myGlobals)
- {
- Str255 aString;
- OSErr iErr;
- Handle prefH;
- if (prefH = NewHandle(sizeof(short)))
- {
- SBGetDetachedIndString(aString, (*myGlobals)->utilityStrings, kPrefName);
- **(short**)prefH = (*myGlobals)->whichString;
- iErr = SBSavePreferences(aString, prefH);
- DisposeHandle(prefH);
- }
- }
- /********
- If the user clicks inside my module's rectangle, I'll get this message.
- If my prefererences are changed, I'll return 2, otherwise 0
- *********/
- long DoCSClick(MyGlobalHandle myGlobals, Rect *statusRect, GrafPtr statusPort)
- {
- Boolean shiftPressed, commandPressed, inMyRect=true;
- Point localPnt;
- long retVal = 0L;
- short oldIndex, newIndex;
- MenuHandle hMenu;
- Str255 debugString;
-
- shiftPressed = IsPressed(kShiftKey);
- commandPressed = IsPressed(kCommandKey);
-
- if (commandPressed) // present a configuration menu
- {
- hMenu = MakePrefsMenu(myGlobals);
- if (hMenu)
- {
- oldIndex = (*myGlobals)->whichString;
- newIndex = SBTrackPopupMenu(statusRect, hMenu);
- if (newIndex && newIndex != oldIndex)
- {
- (*myGlobals)->whichString = newIndex;
- retVal = (1L<< sdevNeedToSave);// set preference changed flag
- }
- DisposeMenu(hMenu);
- }
- if (!shiftPressed || !newIndex) return (retVal);
- // else execute immediately (inMyRect was initialized to true)
- }
- else // manually track mouse
- {
- do
- {
- GetMouse(&localPnt);
- inMyRect = PtInRect(localPnt,statusRect);
- }while (StillDown());
- }
- if (inMyRect)
- {
- SBGetDetachedIndString(debugString,
- (*myGlobals)->debuggerStrings, (*myGlobals)->whichString);
-
- if (debugString[0])
- DebugStr(debugString);
- else
- Debugger();
- }
- return (retVal);
- }
-
- MenuHandle MakePrefsMenu(MyGlobalHandle myGlobals)
- {
- MenuHandle retVal = 0L;
- Str255 menuItem;
- Str63 dummy;
- short item = 1, numItems;
- short **numItemsH;
- dummy[0] = 0;
- retVal = NewMenu(702,dummy); // arbitrary menu id, no title
-
- if (retVal)
- {
- numItemsH = (short**) (*myGlobals)->menuStrings;
- numItems = **numItemsH; // manually find out how many strings I have
- for(item = 1; item<= numItems; item++)
- {
- SBGetDetachedIndString(menuItem, (*myGlobals)->menuStrings, item);
-
- AppendMenu(retVal,menuItem); // note that the string shouldn't start with a -
- // unless you want a grey line
- }
- if ((*myGlobals)->whichString <= numItems)
- SetItemMark(retVal,(*myGlobals)->whichString,sdevMenuItemMark); // the bullet
- }
- return(retVal);
- }
- /*
- DoCSInit -- returns a handle to my allocated globals or -1 if the environment is
- wrong or I couldn't allocate my memory/load my resources
- */
- long DoCSInit(void)
- {
- MyGlobalHandle myH;
- OSErr iErr;
- Handle iconSuite = 0L;
- Handle menuStrings, debugStrings, utilityStrings;
- Str255 prefName;
- short **whichStringH;
- if (HasDebugger()) // is a debugger installed?
- {
- myH = (MyGlobalHandle) NewHandleClear(sizeof(MyGlobals));
- iErr = SBGetDetachIconSuite(&iconSuite, 669, 0x0000FF00L);
- menuStrings = GetDetachedStrings(kMenuStrings);
- debugStrings = GetDetachedStrings(kDebuggerStrings);
- utilityStrings = GetDetachedStrings(kUtilityStrings);
-
- if (myH && iconSuite && menuStrings && debugStrings && utilityStrings)
- // was I able to allocate my memory?
- {
- (*myH)->menuStrings = menuStrings;
- (*myH)->debuggerStrings = debugStrings;
- (*myH)->utilityStrings = utilityStrings;
- (*myH)->iconSuite = iconSuite;
-
- SBGetDetachedIndString(prefName, utilityStrings, kPrefName);
- iErr = SBLoadPreferences(prefName, (Handle*) &whichStringH);
- if (!iErr && whichStringH)
- {
- (*myH)->whichString = **whichStringH;
- DisposeHandle((Handle)whichStringH);
- }
- else (*myH)->whichString = 1; // default
-
- return ((long) myH); // return my globals
- }
- else // failed to allocate all my needed memory
- {
- if(myH) DisposeHandle((Handle) myH);
- if(iconSuite) DisposeIconSuite (iconSuite, true);
- if (menuStrings) DisposeHandle(menuStrings);
- if (debugStrings) DisposeHandle(debugStrings);
- if (utilityStrings) DisposeHandle(utilityStrings);
- }
- }
- return (-1L); // something went wrong, don't install
- }
- /*
- DoCSClose, basically just deallocate all my memory
- */
- void DoCSClose(MyGlobalHandle myGlobals)
- {
- if (myGlobals)
- {
- DisposeIconSuite ((*myGlobals)->iconSuite, true);
- DisposeHandle((*myGlobals)->menuStrings);
- DisposeHandle((*myGlobals)->debuggerStrings);
- DisposeHandle((*myGlobals)->utilityStrings);
- DisposeHandle((Handle) myGlobals);
- }
- }
- /*
- DoCSDraw, just draw my icon. Remember that sometimes the rectangle
- that gets passed will be narrower than the one expected (if your module
- is the last visible module and the strip isn't long enough to draw the
- whole thing.
- */
- void DoCSDraw(MyGlobalHandle myGlobals, Rect *statusRect, GrafPtr statusPort)
- {
- OSErr iErr;
- short alignment = kAlignAbsoluteCenter; // center up & down , and left & right
- long transform = kTransformNone; // no transform
- Rect iconRect;
- if ((*myGlobals)->iconSuite)
- {
- iconRect.left = statusRect->left; iconRect.top = statusRect->top;
- iconRect.bottom = statusRect->bottom;
- iconRect.right = iconRect.left + 16; // I don't want icon squished if the
- // status rect is too narrow (rely on clipping)
- iErr = PlotIconSuite(&iconRect,alignment,transform,(*myGlobals)->iconSuite);
- }
- }
- /*
- As I shouldn't access my module's resource file after initialization, I use
- this routine to load in my STR# resources and convert them to regular
- (non resource) relocatable blocks
- */
- Handle GetDetachedStrings(short id)
- {
- Handle strH;
- strH = Get1Resource('STR#',id);
- if (strH)
- {
- DetachResource(strH);
- }
- return(strH);
- }
- /*
- IsPressed returns true if the given key is being pressed. I use this to
- check the modifier key states
- */
- Boolean IsPressed(unsigned short key)
- {
- unsigned char keyMap[16];
- GetKeys((unsigned long *)&keyMap);
- return((keyMap[key>>3]>>(key & 7)) & 1);
- }
- /*
- The following is a technical improvement on my original HasDebugger()
- routine. This is based on information found in a snippet under the path
- sample code/snippets/platforms & tools/debuggerpresence, and also some
- info in Think Reference
- */
- Boolean HasDebugger(void)
- {
- char *debugFlagPtr;
- short debugFlags;
- if (Can32Bit()) // machine is capable of using 32-bit addressing (might be in 24-bit mode)
- {
- debugFlagPtr = (char *) 0xBFFL; // location of debugger info flags if 32 bit possible
- }
- else
- {
- debugFlagPtr = (char *) 0x120L; // location of debugger info flags if 32 bit impossible
- }
- debugFlags = *debugFlagPtr;
- if (debugFlags & 1<<5) // test debugger present flag
- return(TRUE);
- else
- return (FALSE);
- }
- Boolean Can32Bit(void) // can this machine be placed in 32-bit mode?
- {
- long addressingMode;
- OSErr iErr;
- iErr = Gestalt(gestaltAddressingModeAttr, &addressingMode);
- if (!iErr && (addressingMode & (1 << gestalt32BitCapable)))
- return (TRUE);
- else
- return (FALSE);
- }